package com.vst.orm.base;

import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import com.vst.orm.util.IgnoreFieldProcessorImpl;
import com.vst.orm.util.JsonValueProcessImpl;

import net.sf.json.JSONArray;
import net.sf.json.JsonConfig;
import net.sf.json.util.CycleDetectionStrategy;

/**
 * Page.
 */
public final class Page<E> implements IPageQuery, IPageResult<E>, Iterable<E> {
	// 分页模式
	enum Mode {
		db, memory
	}

	public static final int DEFAULT_PAGE = 1;
	public static final int DEFAULT_PAGESIZE = 1;
	public static final boolean DEFAULT_AUTOCOUNT = true;
	public static final int DEFAULT_TOTALCOUNT = 0;

	private int page = DEFAULT_PAGE;
	private int pagesize = DEFAULT_PAGESIZE;
	private boolean autoCount = DEFAULT_AUTOCOUNT;
	private int totalCount = DEFAULT_TOTALCOUNT;
	private Mode mode = Mode.db;
	private List<E> results = new ArrayList<E>();
	private JSONArray jsonResults = new JSONArray();
	private IgnoreFieldProcessorImpl filter = new IgnoreFieldProcessorImpl(true);
    private Map dateFormat; 
	public static <E> Page<E> get(int page, int pagesize, boolean autoCount) {
		return new Page<E>(page, pagesize, autoCount);
	}

	public static <E> Page<E> get(int page, int pagesize) {
		return get(page, pagesize, true);
	}

	public Page<E> data(int total, List<E> data) {
		return this.setTotal(total).data(data);
	}

	public Page<E> data(List<E> data) {
		if (isMemoryPage(data)) {
			this.mode = Mode.memory;
			setTotal(data.size());
			this.results = MemoryPageUtil.getPageResults(page, pagesize, data);
		} else {
			this.results = data;
		}

		if (this.results == null) {
			this.results = new ArrayList<E>();
		}
		return this;
	}

	private boolean isMemoryPage(List<?> data) {
		return (mode == Mode.memory || data.size() > this.pagesize);
	}

	private Page<E> setTotal(int totalCount) {
		this.totalCount = totalCount;
		return this;
	}

	private Page(int page, int pageSize, boolean autoCount) {
		this.page = (page < DEFAULT_PAGE) ? DEFAULT_PAGE : page;
		this.pagesize = pageSize < DEFAULT_PAGESIZE ? DEFAULT_PAGESIZE
				: pageSize;

		this.autoCount = autoCount;
	}

	public Page<E> setMode(Mode mode) {
		this.mode = mode;
		return this;
	}

	public Page<E> memoryMode() {
		return setMode(Mode.memory);
	}

	/**
	 * 当前页序号.
	 */
	public int getPage() {
		return page;
	}

	/**
	 * 每页结果数.
	 */
	public int getPagesize() {
		return pagesize;
	}

	/**
	 * 是否计算总数?
	 */
	public boolean getAutoCount() {
		return autoCount;
	}

	/**
	 * 总数.
	 */
	public int getTotalCount() {
		return totalCount;
	}

	/**
	 * 获取分页结果集.
	 * 
	 * @return 当页结果集
	 */
	public List<E> getResults() {
		return results;
	}
	
	/**
	 * 参数filter为过滤条件，具体使用查看IgnoreFieldProcessorImpl的构造函数
	 * 
	 *@return void
	 */
	@Deprecated
	public void filterResults(IgnoreFieldProcessorImpl filter){
		this.filter = filter;
	}
	
	/**
	 * 
	 *@param @param ignoreColl 是否忽略集合
	 *@param @param fields 忽略的属性名称
	 *@param @param dateFormat 格式时间
	 *@return void
	 *@throws
	 */
	public void filterResults(boolean ignoreColl, String[] fields, Map dateFormat){
		this.filter = new IgnoreFieldProcessorImpl(ignoreColl,fields,dateFormat);
		this.dateFormat = dateFormat;
	}
	
	/**
	 * 获取分页JSONArray结果集
	 * 
	 *@return JSONArray
	 */
	public Object[] formJsonArrayResults(){
		
		JsonConfig jsonConfig = new JsonConfig();
		jsonConfig.setCycleDetectionStrategy(CycleDetectionStrategy.LENIENT);
		jsonConfig.registerJsonValueProcessor(Date.class, new JsonValueProcessImpl(dateFormat));
	    jsonConfig.setJsonPropertyFilter(filter);
	    jsonResults = JSONArray.fromObject(results, jsonConfig);
		return new Object[]{results,jsonResults};
		
	}
	
	/**
	 * 转换results为JSONArray
	 * 
	 *@return JSONArray
	 */
	public JSONArray getJsonResults(){
		
		if(jsonResults.size() <= 0)
		{
			formJsonArrayResults();
		}
		
		return jsonResults;
	}
	
	/**
	 * 根据pageNo和pageSize计算当前页第一条记录在总结果集中的位置.
	 * <p/>
	 * 序号从0(猴子...)开始.
	 * 
	 * @return the first result item index of total.
	 */
	public int getStart() {
		return (page - 1) * pagesize;
	}

	/**
	 * 获取总页数.
	 * 
	 * @return 总页数,则返回 -1 如果记录数为 0
	 */
	public int getTotalPage() {
		if (totalCount <= 0) {
			return DEFAULT_TOTALCOUNT;
		}

		int count = totalCount / pagesize;
		if (totalCount % pagesize > 0) {
			count++;
		}

		return count;
	}

	/**
	 * 有下一页?
	 */
	public boolean isHasPrePage() {
		return page > 1;
	}

	/**
	 * 是最后一页?
	 */
	public boolean isHasNextPage() {
		return page < getTotalPage();
	}

	/**
	 * 上一页 序号.
	 */
	public int getPrePage() {
		return isHasPrePage() ? page - 1 : 1;
	}

	/**
	 * 下一页序号.
	 */
	public int getNextPage() {
		return isHasNextPage() ? page + 1 : page;
	}

	public Iterator<E> iterator() {
		return results.iterator();
	}

	public Mode getMode() {
		return this.mode;
	}

}

interface IPageResult<E> {

	int getTotalCount();

	List<E> getResults();

	int getTotalPage();

	boolean isHasPrePage();

	boolean isHasNextPage();

	int getPrePage();

	int getNextPage();

	Page.Mode getMode();
}

interface IPageQuery {

	int getPage();

	int getPagesize();

	int getStart();

	boolean getAutoCount();
}

class MemoryPageUtil {
	public static <E> List<E> getPageResults(int page, int pagesize,
			List<E> data) {
		if (data.size() <= pagesize) {
			return data;
		}

		final int start = (page - 1) * pagesize;
		if (start >= data.size()) {
			return new ArrayList();
		}
		final int end = (start + pagesize) > data.size() ? data.size()
				: (start + pagesize);

		return data.subList(start, end);
	}
}